#!/bin/sh /etc/rc.common
#
# Copyright (C) 2019-2021 pexcn <i@pexcn.me>
#
# This is free software, licensed under the GNU General Public License v3.
# See /LICENSE for more information.
#

START=17

USE_PROCD=1
#PROCD_DEBUG=1

CRON_FILE=/etc/crontabs/root

append_param() {
	local section="$1"
	local option="$2"
	local switch="$3"
	local default="$4"
	local _loctmp
	config_get _loctmp "$section" "$option" "$default"
	[ -n "$_loctmp" ] || return 0
	procd_append_param command "$switch" "$_loctmp"
}

append_bool() {
	local section="$1"
	local option="$2"
	local value="$3"
	local default="$4"
	local _loctmp
	config_get_bool _loctmp "$section" "$option" "$default"
	[ "$_loctmp" = 1 ] || return 0
	procd_append_param command "$value"
}

append_param_if_neq() {
	local section="$1"
	local option="$2"
	local switch="$3"
	local compare="$4"
	local _loctmp
	config_get _loctmp "$section" "$option"
	[ -n "$_loctmp" ] || return 0
	[ "$_loctmp" != "$compare" ] || return 0
	procd_append_param command "$switch" "$_loctmp"
}

add_cron() {
	local enable
	local auto_update
	config_get_bool enable $1 enable
	config_get_bool auto_update $1 auto_update
	touch $CRON_FILE
	sed -i '/chinadns-ng_update/d' $CRON_FILE
	([ "$enable" = 1 ] && [ "$auto_update" = 1 ]) && echo "0 3 * * 6 /usr/bin/chinadns-ng_update.sh >>/tmp/chinadns-ng_update.log 2>&1" >>$CRON_FILE
	crontab $CRON_FILE
}

del_cron() {
	sed -i '/chinadns-ng_update/d' $CRON_FILE
	/etc/init.d/cron restart
}

get_cpu_cores() {
	grep -c ^processor /proc/cpuinfo
}

is_exist_ipset() {
	ipset list -n $1 &>/dev/null
}

destroy_ipset() {
	ipset flush $1 2>/dev/null
	ipset destroy $1 2>/dev/null
}

create_chnroute_ipset() {
	local enable
	config_get_bool enable $1 enable
	[ "$enable" = 1 ] || return 0

	config_foreach create_ipv4_ipset chinadns-ng
	config_foreach create_ipv6_ipset chinadns-ng
}

create_ipv4_ipset() {
	local ipset_name
	config_get ipset_name $1 "ipset_name4" "chnroute"

	if is_exist_ipset $ipset_name; then
		ipset flush $ipset_name
	else
		ipset create $ipset_name hash:net hashsize 64 family inet
	fi

	# import ipv4 chnroute
	ipset restore <<- EOF
		$(cat /etc/chinadns-ng/chnroute.txt | sed "s/^/add $ipset_name /")
	EOF
}

create_ipv6_ipset() {
	local ipset_name
	config_get ipset_name $1 "ipset_name6" "chnroute6"

	if is_exist_ipset $ipset_name; then
		ipset flush $ipset_name
	else
		ipset create $ipset_name hash:net hashsize 64 family inet6
	fi

	# import ipv6 chnroute
	ipset restore <<- EOF
		$(cat /etc/chinadns-ng/chnroute6.txt | sed "s/^/add $ipset_name /")
	EOF
}

destroy_chnroute_ipset() {
	# force destroy, even though does not exist or config file changed
	config_foreach destroy_ipv4_ipset chinadns-ng
	config_foreach destroy_ipv6_ipset chinadns-ng
}

destroy_ipv4_ipset() {
	local ipset_name
	config_get ipset_name $1 "ipset_name4" "chnroute"
	destroy_ipset $ipset_name
}

destroy_ipv6_ipset() {
	local ipset_name
	config_get ipset_name $1 "ipset_name6" "chnroute6"
	destroy_ipset $ipset_name
}

start_chinadns_ng() {
	local enable
	config_get_bool enable $1 enable
	[ "$enable" = 1 ] || return 0

	local reuse_port instances=$(get_cpu_cores)
	config_get_bool reuse_port $1 reuse_port
	[ "$reuse_port" = 1 ] || instances=1

	for i in $(seq 1 $instances)
	do
		procd_open_instance
		procd_set_param respawn
		procd_set_param stderr 1
		procd_set_param nice -5
		procd_set_param limits nofile="1048576 1048576"
		procd_set_param command /usr/bin/chinadns-ng
		append_param $1 bind_addr "-b"
		append_param $1 bind_port "-l"
		append_param $1 china_dns "-c"
		append_param $1 trust_dns "-t"
		append_param_if_neq $1 ipset_name4 "-4" "chnroute"
		append_param_if_neq $1 ipset_name6 "-6" "chnroute6"
		append_param $1 gfwlist_file "-g"
		append_param $1 chnlist_file "-m"
		append_param_if_neq $1 timeout_sec "-o" "5"
		append_param_if_neq $1 repeat_times "-p" "1"
		append_bool $1 chnlist_first "-M"
		append_bool $1 no_ipv6 "-N"
		append_bool $1 fair_mode "-f"
		append_bool $1 reuse_port "-r"
		append_bool $1 noip_as_chnip "-n"
		procd_close_instance
	done
}

service_triggers() {
	procd_add_reload_trigger "chinadns-ng"
}

start_service() {
	config_load chinadns-ng
	config_foreach create_chnroute_ipset chinadns-ng
	config_foreach add_cron chinadns-ng
	config_foreach start_chinadns_ng chinadns-ng
}

stop_service() {
	config_load chinadns-ng
	config_foreach destroy_chnroute_ipset chinadns-ng
	del_cron
}

reload_service() {
	stop
	start
}
